package xyz.ddlnt.servicegeneral.util;

import io.micrometer.common.util.StringUtils;
import io.minio.*;
import io.minio.http.Method;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import xyz.ddlnt.model.vo.FileUploadVO;
import xyz.ddlnt.servicegeneral.config.MinIOClientConfig;
import xyz.ddlnt.servicegeneral.config.configProperties.MinIOConfigProperties;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;


/**
 * @author ZZULI_SE 210910
 * @data 2025/4/23 17:33
 */

@Slf4j
@Component
public class MinIOUtils {

    @Resource
    private MinIOConfigProperties minIOConfigProperties;


    /**
     * Minio文件上传
     *
     * @param file  文件实体
     * @return
     */
    public FileUploadVO minioUpload(MultipartFile file ) {
        try {
            MinioClient minioClient = MinIOClientConfig.getMinioClient();
            if (minioClient == null) {
                throw new RuntimeException("连接MinIO服务器失败");
            }
            log.info("文件上传开始：{}",file.getOriginalFilename());

            // 判断存储桶是否存在
            String bucketName = minIOConfigProperties.getBucketName();
            boolean exists = MinIOClientConfig.bucketExists(bucketName);
            if (!exists) {
                log.info("存储桶不存在！创建存储桶...");
                createBucketName(bucketName);
            }else {
                log.info("存储桶存在！");
            }


            // 获取文件后缀名，并生成UUID文件名
            String fileType = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            String UUIDFileName = UUID.randomUUID().toString().replaceAll("-", "") + fileType;

            // 文件上传
            InputStream inputStream = file.getInputStream();
            PutObjectArgs objectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object("/"+minIOConfigProperties.getFolder()+"/"+UUIDFileName)
                    .stream(inputStream, file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build();
            //文件名称相同会覆盖
            ObjectWriteResponse objectWriteResponse = minioClient.putObject(objectArgs);
            log.info("文件上传成功！");

            // 生成随机数作为id
            String seed = objectWriteResponse.etag() + objectWriteResponse.versionId();
            Integer id = new Random(seed.hashCode()).nextInt(Integer.MAX_VALUE);

            // 获取文件预览地址
            String Url = minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(Method.GET)
                            .bucket(bucketName)
                            .object("/"+minIOConfigProperties.getFolder()+"/"+UUIDFileName)
                            .build());
            log.info("获取文件URL！");
            return FileUploadVO.builder().fileId(id).fileUrl(Url).build();
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new RuntimeException("上传文件失败");
        }
    }


    /**
     * 获取文件流
     *
     * @param fileName   文件名
     * @param bucketName 桶名（文件夹）
     * @return
     */
    public InputStream getFileInputStream(String fileName, String bucketName) {
        try {
            MinioClient minioClient = MinIOClientConfig.getMinioClient();
            return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }

    /**
     * @param bucketName:
     * @author
     * @description: 创建桶
     * @date 2022/8/16 14:36
     */
    public void createBucketName(String bucketName) {
        try {
            if (StringUtils.isBlank(bucketName)) {
                return;
            }
            MinioClient minioClient = MinIOClientConfig.getMinioClient();
            boolean isExist = MinIOClientConfig.bucketExists(bucketName);
            if (isExist) {
                log.info("Bucket {} already exists.", bucketName);
            } else {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }


    /**
     * 下载文件
     *
     * @param originalName 文件路径
     */
    public InputStream downloadFile(String bucketName, String originalName, HttpServletResponse response) {
        try {
            MinioClient minioClient = MinIOClientConfig.getMinioClient();
            if (minioClient == null) {
                throw new RuntimeException("连接MinIO服务器失败");
            }

            InputStream file = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(originalName).build());
            String filename = new String(originalName.getBytes("ISO8859-1"), StandardCharsets.UTF_8);
            if (StringUtils.isNotBlank(originalName)) {
                filename = originalName;
            }
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            ServletOutputStream servletOutputStream = response.getOutputStream();
            int len;
            byte[] buffer = new byte[1024];
            while ((len = file.read(buffer)) > 0) {
                servletOutputStream.write(buffer, 0, len);
            }
            servletOutputStream.flush();
            file.close();
            servletOutputStream.close();
            return file;
        } catch (Exception e) {
           log.error(e.getMessage());
            return null;
        }
    }

    /**
     * @param bucketName:
     * @description: 删除桶
     * @date 2022/8/16 14:36
     */
    public void deleteBucketName(String bucketName) {
        try {
            if (StringUtils.isBlank(bucketName)) {
                return;
            }
            MinioClient minioClient = MinIOClientConfig.getMinioClient();
            if (minioClient == null) {
                throw new RuntimeException("连接MinIO服务器失败");
            }
            boolean isExist = MinIOClientConfig.bucketExists(bucketName);
            if (isExist) {
                minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }
    /**
     * @param bucketName:
     * @description: 删除桶下面所有文件
     * @date 2022/8/16 14:36
     */
    public void deleteBucketFile(String bucketName) {
        try {
            if (StringUtils.isBlank(bucketName)) {
                return;
            }
            MinioClient minioClient = MinIOClientConfig.getMinioClient();
            if (minioClient == null) {
                throw new RuntimeException("连接MinIO服务器失败");
            }
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (isExist) {
                minioClient.deleteBucketEncryption(DeleteBucketEncryptionArgs.builder().bucket(bucketName).build());
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }
}
